package com.itzdm.friend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itzdm.client.client.MessageClient;
import com.itzdm.client.client.UserClient;
import com.itzdm.client.domain.UserSearchDto;
import com.itzdm.common.context.UserContext;
import com.itzdm.common.exception.BadRequestException;
import com.itzdm.common.result.PageResult;
import com.itzdm.friend.domain.dto.FriendRemarkDto;
import com.itzdm.friend.domain.dto.FriendRequestDto;
import com.itzdm.friend.domain.dto.HandleRequestDto;
import com.itzdm.friend.domain.po.Friend;
import com.itzdm.friend.domain.vo.FriendGetVo;
import com.itzdm.friend.domain.vo.FriendRequestVo;
import com.itzdm.friend.domain.vo.FriendSearchVo;
import com.itzdm.friend.domain.vo.FriendListVo;
import com.itzdm.friend.enums.FriendType;
import com.itzdm.friend.mapper.FriendMapper;
import com.itzdm.friend.service.IFriendService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.Set;

/**
 * @作者：张德明
 * @时间：2025/4/7 15:47
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> implements IFriendService {

    private final UserClient userClient;
    private final RedisTemplate redisTemplate;
    private final MessageClient messageClient;
    /**
     * 好友列表缓存key前缀
     */
    private static final String FRIEND_LIST_KEY = "friend:list:";

    /**
     * 好友列表缓存过期时间（1小时）
     */
    private static final long FRIEND_LIST_TTL = 3600L;

    /**
     * 搜索陌生人
     *
     * @param keyword
     * @return
     */
    @Override
    public FriendSearchVo searchFriend(String keyword) {
        // 获取用户信息
        UserSearchDto userInfo = userClient.getUserInfo(keyword);
        if (userInfo == null) {
            throw new BadRequestException("用户不存在");
        }

        // 检查用户是否允许被搜索
        if (userInfo.getSearchEnabled() == 0) {
            throw new BadRequestException("该用户不允许被搜索");
        }

        // 构建返回对象
        FriendSearchVo friendSearchVo = new FriendSearchVo();
        BeanUtils.copyProperties(userInfo, friendSearchVo);

        // 查询是否为好友
        Long userId = UserContext.getUser();
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, userId)
                .eq(Friend::getFriendUserId, userInfo.getId());
        Friend friend = this.getOne(queryWrapper);
        if (friend != null) {
            friendSearchVo.setIsFriend(friend.getStatus());
        }
        return friendSearchVo;
    }

    @Override
    public void requestFriend(FriendRequestDto friendRequestDto) {
        Long target = friendRequestDto.getTarget();
        Long userId = UserContext.getUser();

        // 检查是否给自己发送好友请求
        if (target.equals(userId)) {
            throw new BadRequestException("不能给自己发送好友请求");
        }

        // 1.查询用户是否存在
        UserSearchDto userInfo = userClient.getUserInfoById(target);
        if (userInfo == null) {
            throw new BadRequestException("用户不存在");
        }

        // 检查用户是否允许被搜索
        if (userInfo.getSearchEnabled() == 0) {
            throw new BadRequestException("该用户不允许被搜索");
        }

        // 2.查询是否已经是好友
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, userId)
                .eq(Friend::getFriendUserId, target);
        Friend friend = this.getOne(queryWrapper);
        if (friend != null) {
            if (Objects.equals(friend.getStatus(), FriendType.ACCEPT.getCode())) {
                throw new BadRequestException("已经是好友了");
            } else if (Objects.equals(friend.getStatus(), FriendType.REQUEST.getCode())) {
                throw new BadRequestException("已经发送过好友请求了");
            } else if (Objects.equals(friend.getStatus(), FriendType.REJECT.getCode())) {
                // 如果之前拒绝了好友请求，则更新状态为请求中
                friend.setStatus(FriendType.REQUEST.getCode());
                friend.setUpdateTime(LocalDateTime.now());
                boolean update = this.updateById(friend);
                if (!update) {
                    throw new BadRequestException("更新好友请求状态失败");
                }
                return;
            }
        }

        // 3.添加好友请求
        Friend friendRequest = new Friend();
        friendRequest.setUserId(userId);
        friendRequest.setFriendUserId(target);
        friendRequest.setStatus(FriendType.REQUEST.getCode());
        friendRequest.setRemark(friendRequestDto.getRemark());
        friendRequest.setCreateTime(LocalDateTime.now());
        friendRequest.setUpdateTime(LocalDateTime.now());

        // 4.保存好友请求
        boolean save = this.save(friendRequest);
        if (!save) {
            throw new BadRequestException("添加好友请求失败");
        }
    }

    @Override
    public List<FriendRequestVo> getFriendRequests() {
        // 获取当前用户ID
        Long userId = UserContext.getUser();

        // 查询当前用户收到的好友请求
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getFriendUserId, userId)
                .eq(Friend::getStatus, FriendType.REQUEST.getCode())
                .orderByDesc(Friend::getCreateTime);
        List<Friend> friendRequests = this.list(queryWrapper);

        // 如果没有好友请求，返回空列表
        if (friendRequests.isEmpty()) {
            return List.of();
        }

        // 获取所有请求用户的ID
        List<Long> requestUserIds = friendRequests.stream()
                .map(Friend::getUserId)
                .toList();

        // 批量获取请求用户的信息
        List<UserSearchDto> requestUsers = userClient.getUserInfoByIds(requestUserIds);

        // 构建返回结果
        return friendRequests.stream().map(friend -> {
            FriendRequestVo vo = new FriendRequestVo();
            // 设置好友请求信息
            vo.setId(friend.getId());
            vo.setCreateTime(friend.getCreateTime());

            // 设置请求用户信息
            requestUsers.stream()
                    .filter(user -> user.getId().equals(friend.getUserId()))
                    .findFirst()
                    .ifPresent(user -> {
                        vo.setUserId(user.getId());
                        vo.setNickname(user.getNickname());
                        vo.setAvatar(user.getAvatar());
                        vo.setGender(user.getGender());
                        vo.setTfId(user.getTfId());
                        vo.setEmail(user.getEmail());
                    });
            return vo;
        }).toList();
    }

    @Override
    public Friend handleRequest(Long requestId, HandleRequestDto handleRequestDto) {
        // 获取当前用户ID
        Long userId = UserContext.getUser();

        // 查询好友请求是否存在
        Friend friendRequest = this.getById(requestId);
        if (friendRequest == null) {
            throw new BadRequestException("好友请求不存在");
        }

        // 验证是否是当前用户的好友请求
        if (!friendRequest.getFriendUserId().equals(userId)) {
            throw new BadRequestException("无权处理此好友请求");
        }

        // 验证请求状态是否为待处理
        if (!Objects.equals(friendRequest.getStatus(), FriendType.REQUEST.getCode())) {
            throw new BadRequestException("该请求已被处理");
        }

        // 根据处理类型更新状态
        if (handleRequestDto.getAccept()) {
            // 接受好友请求
            friendRequest.setStatus(FriendType.ACCEPT.getCode());
            friendRequest.setUpdateTime(LocalDateTime.now());

            // 创建双向好友关系
            Friend reverseFriend = new Friend();
            reverseFriend.setUserId(friendRequest.getFriendUserId());
            reverseFriend.setFriendUserId(friendRequest.getUserId());
            reverseFriend.setStatus(FriendType.ACCEPT.getCode());
            reverseFriend.setCreateTime(LocalDateTime.now());
            reverseFriend.setUpdateTime(LocalDateTime.now());

            // 保存双向好友关系
            this.save(reverseFriend);
        } else {
            // 拒绝好友请求
            friendRequest.setStatus(FriendType.REJECT.getCode());
            friendRequest.setUpdateTime(LocalDateTime.now());
        }

        // 更新好友请求状态
        boolean update = this.updateById(friendRequest);
        if (!update) {
            throw new BadRequestException("处理好友请求失败");
        }

        // 如果接受好友请求，清除所有相关缓存
        if (handleRequestDto.getAccept()) {
            // 1. 清除发送方的好友列表相关缓存
            String senderCountKey = FRIEND_LIST_KEY + friendRequest.getUserId() + ":count";
            redisTemplate.delete(senderCountKey);

            // 2. 清除接收方的好友列表相关缓存
            String receiverCountKey = FRIEND_LIST_KEY + friendRequest.getFriendUserId() + ":count";
            redisTemplate.delete(receiverCountKey);

            // 3. 删除发送方和接收方的所有分页缓存
            String senderPattern = FRIEND_LIST_KEY + friendRequest.getUserId() + ":*";
            String receiverPattern = FRIEND_LIST_KEY + friendRequest.getFriendUserId() + ":*";

            Set<String> senderKeys = redisTemplate.keys(senderPattern);
            Set<String> receiverKeys = redisTemplate.keys(receiverPattern);

            if (senderKeys != null && !senderKeys.isEmpty()) {
                redisTemplate.delete(senderKeys);
            }

            if (receiverKeys != null && !receiverKeys.isEmpty()) {
                redisTemplate.delete(receiverKeys);
            }

            log.info("好友关系更新，清除相关缓存，发送方ID={}, 接收方ID={}",
                    friendRequest.getUserId(), friendRequest.getFriendUserId());
        }
        return friendRequest;
    }

    /**
     * 获取我的好友列表（分页）
     *
     * @param page 页码，从1开始
     * @param size 每页大小
     * @return
     */
    @Override
    public PageResult getMyFriendList(Integer page, Integer size) {
        // 获取当前用户ID
        Long userId = UserContext.getUser();

        // 参数校验
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }

        // 尝试从缓存中获取好友列表总数
        String cacheCountKey = FRIEND_LIST_KEY + userId + ":count";
        String cachePageKey = FRIEND_LIST_KEY + userId + ":" + page + ":" + size;

        // 尝试从缓存获取当前页数据
        List<FriendListVo> cachedPageData = (List<FriendListVo>) redisTemplate.opsForValue().get(cachePageKey);
        Long cachedTotal = (Long) redisTemplate.opsForValue().get(cacheCountKey);

        if (cachedPageData != null && cachedTotal != null) {
            log.info("从缓存中获取好友列表分页数据，userId={}, page={}, size={}", userId, page, size);
            return new PageResult(cachedTotal, cachedPageData);
        }

        // 缓存未命中，使用MyBatis-Plus分页查询
        log.info("从数据库中获取好友列表，userId={}, page={}, size={}", userId, page, size);

        // 创建分页对象
        Page<Friend> pageParam = new Page<>(page, size);

        // 构建查询条件
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, userId)
                .eq(Friend::getStatus, FriendType.ACCEPT.getCode())
                .orderByDesc(Friend::getUpdateTime); // 按更新时间倒序排序

        // 执行分页查询
        this.page(pageParam, queryWrapper);

        // 如果没有好友，返回空结果
        List<Friend> friendList = pageParam.getRecords();
        if (friendList.isEmpty()) {
            return new PageResult(0, List.of());
        }

        // 获取好友用户ID列表
        List<Long> friendUserIds = friendList.stream()
                .map(Friend::getFriendUserId)
                .toList();

        // 批量获取好友信息
        List<UserSearchDto> friendUsers = userClient.getUserInfoByIds(friendUserIds);

        // 构建结果列表
        List<FriendListVo> resultList = new ArrayList<>(friendList.size());
        for (Friend friend : friendList) {
            // 查找对应的用户信息
            UserSearchDto userInfo = friendUsers.stream()
                    .filter(u -> u.getId().equals(friend.getFriendUserId()))
                    .findFirst()
                    .orElse(null);

            if (userInfo != null) {
                FriendListVo vo = new FriendListVo();
                vo.setUserId(userInfo.getId());
                vo.setNickname(userInfo.getNickname());
                vo.setAvatar(userInfo.getAvatar());
                vo.setGender(userInfo.getGender());
                vo.setSignature(userInfo.getSignature());
                vo.setRemark(friend.getRemark());
                vo.setTfId(userInfo.getTfId());
                vo.setEmail(userInfo.getEmail());
                resultList.add(vo);
            }
        }

        // 缓存结果，有效期为1小时
        redisTemplate.opsForValue().set(cachePageKey, resultList, FRIEND_LIST_TTL, TimeUnit.SECONDS);
        redisTemplate.opsForValue().set(cacheCountKey, pageParam.getTotal(), FRIEND_LIST_TTL, TimeUnit.SECONDS);
        log.info("好友列表分页数据已缓存，userId={}, page={}, size={}, total={}",
                userId, page, size, pageParam.getTotal());

        // 返回分页结果
        return new PageResult(pageParam.getTotal(), resultList);
    }

    @Override
    public void deleteFriend(Long friendUserId) {
        // 获取当前用户ID
        Long userId = UserContext.getUser();

        // 查询是否为好友关系
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, userId)
                .eq(Friend::getFriendUserId, friendUserId)
                .eq(Friend::getStatus, FriendType.ACCEPT.getCode());
        Friend friend = this.getOne(queryWrapper);

        if (friend == null) {
            throw new BadRequestException("该用户不是您的好友");
        }

        // 删除双向好友关系
        // 1. 删除自己的好友记录
        this.removeById(friend.getId());

        // 2. 删除对方的好友记录
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, friendUserId)
                .eq(Friend::getFriendUserId, userId)
                .eq(Friend::getStatus, FriendType.ACCEPT.getCode());
        Friend reverseFriend = this.getOne(queryWrapper);
        if (reverseFriend != null) {
            this.removeById(reverseFriend.getId());
        }

        // 删除双方的聊天记录
        messageClient.deleteMessage(userId, friendUserId);


        // 删除双方的好友列表缓存
        String userPattern = FRIEND_LIST_KEY + userId + ":*";
        String friendPattern = FRIEND_LIST_KEY + friendUserId + ":*";

        Set<String> userKeys = redisTemplate.keys(userPattern);
        Set<String> friendKeys = redisTemplate.keys(friendPattern);

        if (userKeys != null && !userKeys.isEmpty()) {
            redisTemplate.delete(userKeys);
            log.info("删除用户好友列表缓存成功，userId={}", userId);
        }

        if (friendKeys != null && !friendKeys.isEmpty()) {
            redisTemplate.delete(friendKeys);
            log.info("删除好友的好友列表缓存成功，friendUserId={}", friendUserId);
        }
    }

    @Override
    public void changeFriendRemark(FriendRemarkDto friendRemarkDto) {
        // 获取当前用户ID
        Long userId = UserContext.getUser();
        Long friendUserId = friendRemarkDto.getFriendId();
        String remark = friendRemarkDto.getRemark();

        // 查询是否为好友关系
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, userId)
                .eq(Friend::getFriendUserId, friendUserId)
                .eq(Friend::getStatus, FriendType.ACCEPT.getCode());
        Friend friend = this.getOne(queryWrapper);

        if (friend == null) {
            throw new BadRequestException("该用户不是您的好友");
        }

        // 更新好友备注
        friend.setRemark(remark);
        friend.setUpdateTime(LocalDateTime.now());
        boolean update = this.updateById(friend);

        if (!update) {
            throw new BadRequestException("修改好友备注失败");
        }

        // 删除好友列表缓存
        String pattern = FRIEND_LIST_KEY + userId + ":*"; // 使用通配符匹配所有相关缓存
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
            log.info("删除好友列表缓存成功，userId={}, pattern={}", userId, pattern);
        }
    }

    /**
     * 获取好友信息
     * @param userId
     * @return
     */
    @Override
    public FriendGetVo getUserInfo(Long userId) {
        // 查询用户信息
        UserSearchDto userInfo = userClient.getUserInfoById(userId);
        if (userInfo == null) {
            throw new BadRequestException("用户不存在");
        }

        // 构建返回对象
        FriendGetVo friendGetVo = new FriendGetVo();
        BeanUtils.copyProperties(userInfo, friendGetVo);

        // 查询好友备注
        LambdaQueryWrapper<Friend> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friend::getUserId, UserContext.getUser())
                .eq(Friend::getFriendUserId, userId)
                .eq(Friend::getStatus, FriendType.ACCEPT.getCode());
        Friend friend = this.getOne(queryWrapper);
        if (friend != null) {
            friendGetVo.setRemark(friend.getRemark());
        }
        return friendGetVo;
    }
}
